En este cuadernos estudiaremos las redes profundas. Implementaremos nuestra propia red utilizando la biblioteca (API) Keras (https://keras.io/).
Identificaremos nuestros mejores modelos según la arquitectura de red, intentando redes multi-capa densamente conectadas y haciendo uso de regularización para el cálculo de su función de pérdida.
Probaremos nuestros modelos más complejos de deep learning para la detección automática de frailejones sobre imagenes aereas del páramo e intentaremos mejorar los resultados que obtuvimos con nuestras redes más sencillas. Recordemos que hasta ahora hemos logrado unos resultados preliminares con un accuracy de validación de 0.86, utilizando una red sencilla de 5 neuronas.
from google.colab import drive
drive.mount('/content/drive')
!cp "drive/My Drive/ImportImagenesRGB.py" .
!cp "drive/My Drive/data_F" .
!cp "drive/My Drive/IMG_3451.JPG" .
!pip install livelossplot
Importemos algunos de los paquetes que vamos a utilizar:
import numpy as np
import h5py
import matplotlib.pyplot as plt
from ImportImagenesRGB import *
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
%load_ext autoreload
%autoreload 2
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
from prettytable import PrettyTable
import datetime
import keras
import tensorflow as tf
from keras.models import Sequential, load_model
from keras.optimizers import SGD
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.callbacks import EarlyStopping, ModelCheckpoint
from livelossplot import PlotLossesKeras
from numpy.random import seed
seed(1)
A continuacion repliquemos el modelo de red sencilla con 5 neuronas que ya construimos paso a paso en clases anteriores. Pero esta vez utilizando la funcion modelde Keras, que añade capas secuencialmente.
Repetimos varias veces el entrenamiento, validación y prueba de los modelos con distintas particiones de los datos, implementando una validación cruzada doble con el fin de obtener una estimación insesgada del error de predicción (para mayores detalles ver Filmozer et al (2009), http://www.libpls.net/publication/rdCV_2009.pdf) Esta implementación es útil cuando tenemos pocos datos.
Para esta primera red sencilla, el proceso de optimización lo vamos a implementar de acuerdo con el método de Descenso en la Dirección del Gradiente Estocástico (SGD). Como ya hemos visto, el método de Descenso en la direccion del gradiente es un método iterativo que permite optimizar funciones objetivo diferenciables, donde
$$ \hat \theta_{nuevo} = \hat \theta_{viejo} - \alpha \frac{\partial J(\hat \theta_{viejo}; X, Y) }{ \partial \hat \theta_{viejo} }$$siendo $\alpha$ la tasa de aprendizaje y $\theta$ nuestro parámetro a estimar.
La parte estocástica se refiere a que en lugar de utilizar todos los datos en cada paso iterativo, utilizamos una observación (elegida de manera aleatoria) en cada paso. De esta manera, el SGD permite reducir el coste computacional del proceso de optimización, iterando más rápidamente pero con un tasa de convergencia ligeramente menor y más oscilante.
Entonces, el SGD se puede formular de la siguiente manera
$$ \hat \theta_{nuevo} = \hat \theta_{viejo} - \alpha \frac{\partial J (\hat \theta_{viejo}; x^{(i)}, y^{(i)})}{ \partial \hat \theta_{viejo} }$$Fijémnos que una variación del GD a medio-camino del SGD es el GD en batches o subconjuntos de datos con un tamaño dado (16, 32, 64,...), el cual optimiza sobre distintos subconjuntos (aleatoriamente seleccionados) del total de los datos en cada iteración.
Además se tienen otras modificaciones sobre el SGD. La más opular es la adición de un término de momentum.
Recordando las nociones de física, el término momentum hace referencia al algoritmo que avanza a lo largo del espacio paramétrico en búsqueda del óptimo (local), aceleradno de acuerdo con el gradiente de la pérdida (que guardando la anlogía con la física, se refiere a la fuerza). De esta manera, modificando el GD clásico, pues mantiene la misma dirección a medida que avanza disminuyendo las oscilaciones.
Este método hace parte de la literatura del aprendizaje computacional basado en la retro-propagación (Rumelhart et al. (1986) https://www.nature.com/articles/323533a0)
El SGD con momentum actualiza los estimadores como una combinación lineal entre el gradiente y la actualización previa, implementando un promedio suavizado:
$$ \hat \theta_{nuevo} = \eta \hat \theta_{viejo} - \alpha \frac{\partial J (\hat \theta_{viejo}; x^{(i)}, y^{(i)})}{ \partial \hat \theta_{viejo} }$$donde $\eta$ es el factor de decrecimiento exponencial que toma valores entre 0 y 1. Así, $\eta$ permite incorporar la contribución relativa entre el gradiente actual y de gradientes anteriores.
A continuación importemos las imagenes:
X,Y = import_imagenes_RGB()
print(X.shape, Y.shape, X[0,0,0])
Salida esperada:
(250, 70, 70, 3) (1, 250) [0.58823529 0.5372549 0.40392157]
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca"])
Acc_E = []
Acc_V = []
Acc_P = []
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=1000
# Definimos los parametros del SGD
sgd = SGD(lr=0.01, momentum=0.001)
# junto con la inicialización aleatoria
initnorm = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=1)
# inicializamos el error para guardar el mejor modelo
err_p = 999
# implementamos 3 repeticiones con particiones distintas de entrenamiento y doble validacion
for i in range(0,3,1):
r = i^3
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = r)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = r)
# Especificamos la arquitectura de la red
model = Sequential()
model.add(Flatten(input_shape=CE_x.shape[1:]))
model.add(Dense(5, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
if (loss_p < err_p):
pathr =('modelo_redsencilla_initseed=1_part_seed='+str(r)+'numn=5.h5')
model.save(pathr)
err_p = loss_p
# Imprimimos el desempeño para cada repetición
print('Epoca= '+str(best_epoc[0])+' y accu_v='+str(accu_v))
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0]])
# Exactitud media
Acc_E.append(accu_e)
Acc_V.append(accu_v)
Acc_P.append(accu_p)
print(x)
print('Accuracies de Entrenamiento: '+str(np.round(np.mean(Acc_E),3))
+'; Validacion1: '+str(np.round(np.mean(Acc_V),3))+ '; Validacion2: '+str(np.round(np.mean(Acc_P),3)))
Graficamos el desempeño del modelo:
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud')
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida')
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
Confirmamos que podemos cargar de nuevo el modelo que guardamos:
# red sencilla 5 neuronas
model_1 = load_model('modelo_redsencilla_initseed=1_part_seed=3numn=5.h5')
Cuántos parámetros debemos estimar en esta red sencilla?
Input_layer = CE_x.shape[1]
Input_bias = 1
Hidden_layer = 5
Hidden_bias = 1
Output_layer = 1
Total_param = (Input_layer+Input_bias)*Hidden_layer+(Hidden_layer+Hidden_bias)*Output_layer
Total_param
Confirmamos el desempeño del modelo sobre todo el conjunto de datos:
Y_pred = model_1.predict(X)
Y_preds = (Y_pred > 0.5)
confusion_matrix(Y.T, Y_preds)
Salida esperada:
| 140 | 5 |
| 7 | 98 |
Busque un mejor modelo intentando diferentes inicializaciones para la estimación de los parámetros.
##### MEJORA 1 --> Inicialización He en capa oculta #######
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca"])
Acc_E = []
Acc_V = []
Acc_P = []
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=1000
# Definimos los parametros del SGD
sgd = SGD(lr=0.01, momentum=0.001)
# junto con la inicialización aleatoria
initnorm = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=1)
initHe = keras.initializers.he_normal(seed=1)
# inicializamos el error para guardar el mejor modelo
err_p = 999
# implementamos 3 repeticiones con particiones distintas de entrenamiento y doble validacion
for i in range(0,3,1):
r = i^3
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = r)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = r)
# Especificamos la arquitectura de la red
model = Sequential()
model.add(Flatten(input_shape=CE_x.shape[1:]))
model.add(Dense(5, activation='sigmoid', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
if (loss_p < err_p):
pathr =('modelo_redsencilla_initseed=1_part_seed='+str(r)+'numn=5.h5')
model.save(pathr)
err_p = loss_p
# Imprimimos el desempeño para cada repetición
print('Epoca= '+str(best_epoc[0])+' y accu_v='+str(accu_v))
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0]])
# Exactitud media
Acc_E.append(accu_e)
Acc_V.append(accu_v)
Acc_P.append(accu_p)
print(x)
print('Accuracies de Entrenamiento: '+str(np.round(np.mean(Acc_E),3))
+'; Validacion1: '+str(np.round(np.mean(Acc_V),3))+ '; Validacion2: '+str(np.round(np.mean(Acc_P),3)))
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud')
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida')
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
R/ Al realizar la inicialización de He se evidencia una mejora en el accuracy que para el escenario inicial no superaba el 0.8.
### Momentum en 0.01 --> Resultados no cambian
### Momentum en 0.1 --> No hubo mejora en los resultados
### stddev = 0.5 --> Empeora resultados Accuracies de Entrenamiento: 0.874; Validacion1: 0.721; Validacion2: 0.754
Ahora implementemos una red multi-capa, añadiendo más capas al modelo. Primero definimos la técnica de inicialización de He que vimos la clase pasada, la cual está pensada para aliviar el entenamiento de redes profundas con funciones de activación basadas en los rectficadores ReLU.
Recordemos que la inicialización de He para los parametros $W^{[l]}$ consiste en multiplicar sus valores iniciales por $\sqrt{\frac{2}{n_l}}$.
Ahora, para esta red profunda, vamos a utilizar un método de optimización que nos ayude a reducir el coste computacional que conlleva un número aumentado de parámetros a estimar.
El método de propagación de la raiz cuadrada del cuadrado medio (RMSProp Root Mean Square Propagation) permite adaptar la tasa de aprendizaje para cada uno de los parámetros. Esto se hace dividiendo la tasa de aprendizaje (para un parámetro) por un promedio móvil de las magnitudes de los gradientes recientes (ver https://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf )
De esta manera, un primer promedio movil se calcula en términos de los cuadrados medios del gradiente y el parámetro $\rho$ que representa un factor de memoria a corto plazo sobre los gradientes recientes:
$$ v(\theta) = \rho v(\theta_{viejo}) + (1-\rho) \biggr( \frac{\partial J (\hat \theta_{viejo}; x^{(i)}, y^{(i)})}{ \partial \hat \theta_{viejo} } \biggl)^2 $$De tal manera que la actualización de los parámetros se lleva a cabo mediante:
$$ \hat \theta_{nuevo} = \hat \theta_{viejo} - \frac{\alpha}{\sqrt{v(\theta)}} \frac{\partial J (\hat \theta_{viejo}; x^{(i)}, y^{(i)})}{ \partial \hat \theta_{viejo} }$$Esta implementación del RMSProp permite adaptar la tasa de aprendizaje sobre la optimización con todos los datos o pequeños subconjuntos de los datos.
Antes de especificar la estructura de la red, primero definamos la inicializacion de He:
initHe = keras.initializers.he_normal(seed=1)
Veamos cómo podemos agregar más capas al modelo que definimos con la ayuda de Keras. A continuación definimos la arquitectura de la red, una con inicializacion aleatoria normal y otra con la incializacion de He:
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_norm = model.get_config()
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initHe, bias_initializer='zeros'))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_He = model.get_config()
Ahora implementamos el codigo para buscar el mejor modelo con la arquitectura arriba definida, probando ambos métodos de incialización:
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca", "Init"])
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=200
# Definimos los parametros del RMSProp
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
x
# implementamos 2 repeticiones, una con inicializacion aleatoria Normal y otra con He
for i in range(2):
if(i==0):
model = Sequential.from_config(config_norm)
init = "Normal"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
elif(i==1):
model = Sequential.from_config(config_He)
init = "He"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
# Partimos los datos en entrenamiento y doble validación
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en la primera validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
pathr =('modelo_redprofunda_initseed=1_part_seed=8_Init='+str(init)+'.h5')
model.save(pathr)
err_p = loss_p
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0], init])
# Imprimimos el desempeño para cada inicializacion y el tiempo en completar las iteraciones
print('Epoca= '+str(best_epoc[0])+' , accu_v1='+str(accu_v) +' , accu_v2='+str(accu_p))
tiempo1 = datetime.datetime.now()
print('Fin Init= ' +str(init)+':' +str(tiempo1))
# Graficamos el desempeño del modelo
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud inicializacion ' +str(init))
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida inicializacion ' +str(init))
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
print(x)
Qué método de inicialización ayuda más a la convergencia del modelo?
R/ A medida que van transcurriendo las épocas la inicialización Normal muestra una mayor estabilidad en los valores de accuracy y de pérdida, mientras que con la inicialización de He se observa mayor varianza.
Cargamos el mejor modelo y confirmamos el desempeño del modelo sobre todo el conjunto de datos:
# red profunda de 6 capas
model_2 = load_model('modelo_redprofunda_initseed=1_part_seed=8_Init=Normal.h5')
model_2.summary()
Y_pred = model_2.predict(X)
Y_preds = (Y_pred > 0.5)
confusion_matrix(Y.T, Y_preds)
Salida esperada (aproximada):
| 139 | 6 |
| 6 | 99 |
Explore la implementación de regularizacion L1 y L2 sobre la última capa escondida para mejorar el desempeño en validación de la red.
*Ayuda: visite la pagina de Keras https://keras.io/regularizers/
para aplicar regularización sobre la magnitud de los parametros, implemente kernel_regularizer
Por ejemplo, si queremos una regularización L2 con una constante de 0.01, escribimos kernel_regularizer=regularizers.l2(0.01)
from tensorflow.keras import regularizers
# Regularización L1
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros', kernel_regularizer=regularizers.l1(0.01)))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_norm = model.get_config()
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca", "Init"])
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=200
# Definimos los parametros del RMSProp
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
x
# implementamos 2 repeticiones, una con inicializacion aleatoria Normal y otra con He
#for i in range(2):
# if(i==0):
model = Sequential.from_config(config_norm)
init = "Normal"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
# elif(i==1):
# model = Sequential.from_config(config_He)
# init = "He"
# tiempo0 = datetime.datetime.now()
# print('Inicio Init=' +str(init)+':' +str(tiempo0))
# Partimos los datos en entrenamiento y doble validación
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en la primera validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
pathr =('modelo_redprofunda_initseed=1_part_seed=8_Init='+str(init)+'.h5')
model.save(pathr)
err_p = loss_p
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0], init])
# Imprimimos el desempeño para cada inicializacion y el tiempo en completar las iteraciones
print('Epoca= '+str(best_epoc[0])+' , accu_v1='+str(accu_v) +' , accu_v2='+str(accu_p))
tiempo1 = datetime.datetime.now()
print('Fin Init= ' +str(init)+':' +str(tiempo1))
# Graficamos el desempeño del modelo
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud inicializacion ' +str(init))
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida inicializacion ' +str(init))
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
print(x)
# Regularización L2
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros', kernel_regularizer=regularizers.l2(0.01)))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_norm = model.get_config()
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca", "Init"])
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=200
# Definimos los parametros del RMSProp
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
x
# implementamos 2 repeticiones, una con inicializacion aleatoria Normal y otra con He
#for i in range(2):
# if(i==0):
model = Sequential.from_config(config_norm)
init = "Normal"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
# elif(i==1):
# model = Sequential.from_config(config_He)
# init = "He"
# tiempo0 = datetime.datetime.now()
# print('Inicio Init=' +str(init)+':' +str(tiempo0))
# Partimos los datos en entrenamiento y doble validación
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en la primera validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
pathr =('modelo_redprofunda_initseed=1_part_seed=8_Init='+str(init)+'.h5')
model.save(pathr)
err_p = loss_p
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0], init])
# Imprimimos el desempeño para cada inicializacion y el tiempo en completar las iteraciones
print('Epoca= '+str(best_epoc[0])+' , accu_v1='+str(accu_v) +' , accu_v2='+str(accu_p))
tiempo1 = datetime.datetime.now()
print('Fin Init= ' +str(init)+':' +str(tiempo1))
# Graficamos el desempeño del modelo
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud inicializacion ' +str(init))
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida inicializacion ' +str(init))
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
print(x)
# Regularización L1_L2
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros', kernel_regularizer=regularizers.l1_l2(l1=0.01,l2=0.01)))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_norm = model.get_config()
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca", "Init"])
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=200
# Definimos los parametros del RMSProp
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
x
# implementamos 2 repeticiones, una con inicializacion aleatoria Normal y otra con He
#for i in range(2):
# if(i==0):
model = Sequential.from_config(config_norm)
init = "Normal"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
# elif(i==1):
# model = Sequential.from_config(config_He)
# init = "He"
# tiempo0 = datetime.datetime.now()
# print('Inicio Init=' +str(init)+':' +str(tiempo0))
# Partimos los datos en entrenamiento y doble validación
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en la primera validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
pathr =('modelo_redprofunda_initseed=1_part_seed=8_Init='+str(init)+'.h5')
model.save(pathr)
err_p = loss_p
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0], init])
# Imprimimos el desempeño para cada inicializacion y el tiempo en completar las iteraciones
print('Epoca= '+str(best_epoc[0])+' , accu_v1='+str(accu_v) +' , accu_v2='+str(accu_p))
tiempo1 = datetime.datetime.now()
print('Fin Init= ' +str(init)+':' +str(tiempo1))
# Graficamos el desempeño del modelo
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud inicializacion ' +str(init))
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida inicializacion ' +str(init))
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
print(x)
Revise los métodos de inicialización, el procedimiento de optimización, la arquitectura de la red y/o las funciones de activación, e intente mejorar los resultados que acabamos de obtener.
# Dividiendo los datos
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Limpiando
keras.backend.clear_session()
# Número de epocas
epocas=200
# Nombre del modelo
modelo = "Exec="+"".join(datetime.datetime.now().strftime('%f'))
# Optimizadores
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
sgd = SGD(lr=0.01, momentum=0.001)
# Tipo de inicialización
initnorm = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=1)
initHe = keras.initializers.he_normal(seed=1)
# Arquitectura
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros', kernel_regularizer=regularizers.l1_l2(l1=0.01,l2=0.01)))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Modelo
#model = Sequential.from_config(config_He)
# Compilando modelo
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Arquitectura del modelo
model.summary()
# Entrenando modelo
#model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Callbacks
fBestModel = 'best_model.h5'
early_stop = EarlyStopping(monitor='accuracy', patience=20, verbose=1)
best_model = ModelCheckpoint(fBestModel, verbose=1, save_best_only=True)
tb_callback = tf.keras.callbacks.TensorBoard(log_dir = "".join(["logs/", modelo]), histogram_freq = 1)
# Corriendo modelo con el mejor ajuste en entrenamiento
model.fit(CE_x, CE_y,
validation_data=(CV_x, CV_y),
epochs=epocas,
#batch_size=528,
verbose = 1,
#validation_split=0.3,
shuffle = False,
callbacks=[tb_callback, early_stop, best_model, PlotLossesKeras()])
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
# Guardamos el modelo
pathr =('modelo_='+modelo+'.h5')
model.save(pathr)
# Valores de exactitud
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca"])
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0]])
print(x)
Y_pred = model.predict(X)
Y_preds = (Y_pred > 0.5)
confusion_matrix(Y.T, Y_preds)
Después de ver los resultados. Se evidencia que la exactitud del modelo en el conjunto de validación y/o en el conjunto de prueba, no mejoran mucho. Se implementa una grilla con Tensorboard y Hparams para ver la evolución con multiples corridas de cada uno de los parametros.
Vamos a modificar los siguientes hiperparámetros:
Se usará la API de hparams que tiene tensorboard. Así mismo, como se mencionó antes, se mostrará en un Tensorboard los parametros indicados enteriormente para evaluar uno a uno y tomar decisiones sobre la mejor arquitectura, optimizador e inicialización.
Puede observar el dashboard de Tensorboard.
!rm -rf ./logs/
from tensorboard.plugins.hparams import api as hp
# Optimizadores
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
sgd = SGD(lr=0.01, momentum=0.001)
# Tipo de inicialización
initnorm = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=1)
initHe = keras.initializers.he_normal(seed=1)
# Nombre del modelo
modelo = "Exec="+"".join(datetime.datetime.now().strftime('%f'))
# Dicccionario de hiperparametros
HP_NUM_UNITS_TWO = hp.HParam('num_units_two', hp.Discrete([100, 300]))
HP_NUM_UNITS = hp.HParam('num_units', hp.Discrete([16, 32]))
HP_DROPOUT = hp.HParam('dropout', hp.RealInterval(0.1, 0.2))
HP_OPTIMIZER = hp.HParam('optimizer', hp.Discrete(['adam', 'sgd', 'rmsprop']))
HP_INIT = hp.HParam('init', hp.Discrete(['RandomNormal', 'he_normal']))
#HP_L2 = hp.HParam('l2 regularizer', hp.RealInterval(.001,.01))
METRIC_ACCURACY = 'accuracy'
# Creando directorio de hiperparametros
with tf.summary.create_file_writer('logs/hparam_tuning').as_default():
hp.hparams_config(
hparams=[HP_NUM_UNITS, HP_NUM_UNITS_TWO, HP_DROPOUT, HP_OPTIMIZER, HP_INIT],
metrics=[hp.Metric(METRIC_ACCURACY, display_name='Accuracy')],
)
def train_test_model(run_dir, hparams):
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=X.shape[1:]),
tf.keras.layers.Dense(700, activation='relu', kernel_initializer=hparams[HP_INIT], bias_initializer='zeros'),
tf.keras.layers.Dense(400, activation='relu', kernel_initializer=hparams[HP_INIT], bias_initializer='zeros'),
tf.keras.layers.Dense(hparams[HP_NUM_UNITS_TWO], activation='relu', kernel_initializer=hparams[HP_INIT], bias_initializer='zeros'),
tf.keras.layers.Dropout(hparams[HP_DROPOUT]),
tf.keras.layers.Dense(50, activation='relu', kernel_initializer=hparams[HP_INIT], bias_initializer='zeros'),
tf.keras.layers.Dense(hparams[HP_NUM_UNITS], activation='relu', kernel_initializer=hparams[HP_INIT], bias_initializer='zeros', kernel_regularizer=regularizers.l1_l2(l1=0.01,l2=0.01)),
tf.keras.layers.Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros')
])
# Callbacks
fBestModel = 'best_model.h5'
early_stop = EarlyStopping(monitor='accuracy', patience=20, verbose=1)
best_model = ModelCheckpoint(fBestModel, verbose=1, save_best_only=True)
model.compile(loss='binary_crossentropy', optimizer=hparams[HP_OPTIMIZER], metrics=['accuracy'])
model.fit(CE_x, CE_y, validation_data=(CV_x, CV_y), epochs=100, callbacks=[tf.keras.callbacks.TensorBoard(run_dir), hp.KerasCallback(run_dir, hparams), PlotLossesKeras(), best_model]) #early_stop
_, accuracy = model.evaluate(CV_x, CV_y)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
# Guardamos el modelo
pathr =('modelo_'+modelo+'.h5')
model.save(pathr)
# Valores de exactitud
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P"])
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4)])
print("\n", x)
Y_pred = model.predict(X)
Y_preds = (Y_pred > 0.5)
confusion_matrix(Y.T, Y_preds)
return accuracy
def run(run_dir, hparams):
with tf.summary.create_file_writer(run_dir).as_default():
hp.hparams(hparams)
accuracy = train_test_model(run_dir, hparams)
tf.summary.scalar(METRIC_ACCURACY, accuracy, step=1)
session_num = 0
for num_units in HP_NUM_UNITS.domain.values:
for num_units_two in HP_NUM_UNITS_TWO.domain.values:
for dropout_rate in (HP_DROPOUT.domain.min_value, HP_DROPOUT.domain.max_value):
for optimizer in HP_OPTIMIZER.domain.values:
for init in HP_INIT.domain.values:
hparams = {
HP_NUM_UNITS: num_units,
HP_NUM_UNITS_TWO: num_units_two,
HP_DROPOUT: dropout_rate,
HP_OPTIMIZER: optimizer,
HP_INIT: init,
}
run_name = "run-%d" % session_num
print('--- Starting trial: %s' % run_name)
print({h.name: hparams[h] for h in hparams})
run('logs/hparam_tuning/' + run_name, hparams)
session_num += 1
!tensorboard dev upload --logdir ./logs/hparam_tuning \
--name "Semana 5: Redes Profundas con Keras" \
--description "Resultados de entrenamiento desde https://sergiomora03.github.io/deep-learning-intermediate/" \
--one_shot
Los resultados pueden observarse en https://tensorboard.dev/experiment/mQfPPEzARJeQwocxAA8gRQ/#hparams
!tensorboard dev list
!tensorboard dev delete --experiment_id m6R2aen9QWq9OgRGKZW96w
%load_ext tensorboard
%tensorboard --logdir logs/
%%bash
wget -q 'https://storage.googleapis.com/download.tensorflow.org/tensorboard/hparam_tuning_logs.zip'
unzip -q hparam_tuning_logs.zip -d logs/hparam_tuning
%tensorboard --logdir logs/hparam_tuning
Probando con regularizaciones
# Optimizadores
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
sgd = SGD(lr=0.01, momentum=0.001)
# Tipo de inicialización
initnorm = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=1)
initHe = keras.initializers.he_normal(seed=1)
# Regularización L2
model = Sequential()
model.add(Flatten(input_shape=X.shape[1:]))
model.add(Dense(700, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(400, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(100, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(50, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros'))
model.add(Dense(15, activation='relu', kernel_initializer=initnorm, bias_initializer='zeros', kernel_regularizer=regularizers.l2(0.01)))
model.add(Dense(1, activation='sigmoid', kernel_initializer=initnorm, bias_initializer='zeros'))
# Guardamos la arquitectura de red
config_norm = model.get_config()
# Inicializamos la tabla donde guardamos los resultados
x = PrettyTable(["Exac_E", "Exac_V", "Exac_P", "Epoca", "Init"])
# Definimos el número máximo de iteraciones (épocas de la red)
epocas=200
# Definimos los parametros del RMSProp
rmsprop = keras.optimizers.RMSprop(lr=0.00008, rho=0.9)
x
# implementamos 2 repeticiones, una con inicializacion aleatoria Normal y otra con He
#for i in range(2):
# if(i==0):
model = Sequential.from_config(config_norm)
init = "Normal"
tiempo0 = datetime.datetime.now()
print('Inicio Init=' +str(init)+':' +str(tiempo0))
# elif(i==1):
# model = Sequential.from_config(config_He)
# init = "He"
# tiempo0 = datetime.datetime.now()
# print('Inicio Init=' +str(init)+':' +str(tiempo0))
# Partimos los datos en entrenamiento y doble validación
CE_x, CV0_x, CE_y, CV0_y = train_test_split(X, Y.T, test_size = 0.3, random_state = 8)
CV_x, CP_x, CV_y, CP_y = train_test_split(CV0_x, CV0_y, test_size = 0.5, random_state = 8)
# Definimos el método de optimización con respecto a su funcion de perdida (además guardamos la exactitud para cada iteracion)
model.compile(loss='binary_crossentropy', optimizer=rmsprop, metrics=['accuracy'])
# Ajustamos el modelo
history=model.fit(x=CE_x, y=CE_y, epochs=epocas, validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Encontramos el mejor modelo en validación
min_err=np.min(history.history['val_loss'])
best_epoc=np.where(history.history['val_loss'] == min_err)[0]
# Conseguimos el mejor modelo de acuerdo con su desempeño en la primera validación
model.fit(x=CE_x, y=CE_y, epochs=best_epoc[0], validation_data=(CV_x, CV_y), verbose=0, shuffle=False)
# Calculamos las metricas
train_metrics = model.evaluate(x=CE_x, y=CE_y, verbose=0)
valid_metrics = model.evaluate(x=CV_x, y=CV_y, verbose=0)
test_metrics = model.evaluate(x=CP_x, y=CP_y, verbose=0)
# Guardamos las métricas de desempeño
accu_e = train_metrics[1]
loss_e = train_metrics[0]
accu_v = valid_metrics[1]
loss_v = valid_metrics[0]
accu_p = test_metrics[1]
loss_p = test_metrics[0]
pathr =('modelo__redprofunda_initseed=1_part_seed=8_Init='+str(init)+'.h5')
model.save(pathr)
err_p = loss_p
x.add_row([np.round(accu_e,4), np.round(accu_v,4), np.round(accu_p,4), best_epoc[0], init])
# Imprimimos el desempeño para cada inicializacion y el tiempo en completar las iteraciones
print('Epoca= '+str(best_epoc[0])+' , accu_v1='+str(accu_v) +' , accu_v2='+str(accu_p))
tiempo1 = datetime.datetime.now()
print('Fin Init= ' +str(init)+':' +str(tiempo1))
# Graficamos el desempeño del modelo
plt.figure(1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Exactitud inicializacion ' +str(init))
plt.ylabel('Acc')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validacion'], loc='lower right')
plt.show()
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Pérdida inicializacion ' +str(init))
plt.ylabel('Pérdida')
plt.xlabel('Epoca')
plt.legend(['Entreno', 'Validación'], loc='upper right')
plt.show()
print(x)
Lectura avanzada sobre métodos de optimización en redes profundas: https://openreview.net/pdf?id=ryQu7f-RZ http://www.cs.utoronto.ca/~ilya/pubs/2013/1051_2.pdf
Ahora probemos nuestro modelo sobre la imagen completa de prueba del paramo IMG_3451.JPG.
from keras.preprocessing import image
img = image.load_img('IMG_3451.JPG')
img